package com.xinsoft.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.ExcelErrRowDTO;
import com.xinsoft.entity.dto.SysWarehouseImportDTO;
import com.xinsoft.entity.dto.SysWarehouseParam;
import com.xinsoft.entity.po.SysDictionary;
import com.xinsoft.entity.po.SysWarehouse;
import com.xinsoft.mapper.SysWarehouseMapper;
import com.xinsoft.service.SysDictionaryService;
import com.xinsoft.service.SysFileHisService;
import com.xinsoft.service.SysWarehouseService;
import com.xinsoft.utils.ExcelUtils;
import com.xinsoft.validator.ValidatorUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author lijie
* @description 针对表【sys_warehouse(仓库)】的数据库操作Service实现
* @createDate 2023-05-24 10:27:21
*/
@Service
public class SysWarehouseServiceImpl extends ServiceImpl<SysWarehouseMapper, SysWarehouse>
    implements SysWarehouseService{

    @Resource
    SysWarehouseMapper sysWarehouseMapper;

    @Resource
    SysDictionaryService sysDictionaryService;

    @Resource
    SysFileHisService sysFileHisService;

    @Override
    public Object findPageListByParam(SysWarehouseParam param) {
        Page<SysWarehouse> page = new Page<SysWarehouse>(param.getCurrentPage(), param.getPageSize());
        LambdaQueryWrapper<SysWarehouse> queryWrapper = new LambdaQueryWrapper<>();
        //查询条件
        queryWrapper
                .like(param.getWareHouseName()!=null,SysWarehouse::getWarehouseName,param.getWareHouseName())
                // 仓库仓位成树场景，只渲染已审核的仓库
                .eq(param.getPoint().equals(Const.AUDIT_STATUS_NORMAL),SysWarehouse::getAuditStatus,Const.PLAN_STATUS_NORMAL);
        IPage<SysWarehouse> resultPage = sysWarehouseMapper.selectPageInfo(page, queryWrapper);
        //返回值
        return resultPage;
    }

    @Override
    public JSONObject importExcel(MultipartFile multipartFile) throws IOException {
        // 初始化错误行信息list，用来记录导入失败的rowNum
        List<ExcelErrRowDTO> errRowDOs = new ArrayList<>();

        // 对excel是否为空进行check
        if (multipartFile.isEmpty()) {
            throw new BDException("导入失败，请选择文件！");
        }

        //设置excel参数
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        List<SysWarehouseImportDTO> sysWarehouseList;
        List<SysWarehouse> sysWarehouses = CollectionUtil.newArrayList();

        JSONObject result = new JSONObject();

        // 解析excel中的行，放到sysWarehouseList中
        try {
            // 解析excel
            sysWarehouseList = ExcelImportUtil.importExcel(multipartFile.getInputStream(), SysWarehouseImportDTO.class, params);
        } catch (Exception e) {
            throw new BDException("导入失败，文件内容解析错误！");
        }

        //校验
        if (sysWarehouseList.size() > 0) {
            //取出excel和db中所有重复的name
            List<String> excelWarehouseNames = sysWarehouseList.stream()
                    .map(SysWarehouseImportDTO::getWarehouseName)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbWarehouseNames = this.getAllWarehouseName();//获取系统中所有的WarehouseName
            List<String> duplicateWarehouseNames = new ArrayList<>(); // 存放存在重复的warehouseName，用于定位重复存放存在重复的warehouseName的行

            if (dbWarehouseNames.size() > 0 && excelWarehouseNames.size() > 0) {
                dbWarehouseNames.addAll(excelWarehouseNames);//合并
                duplicateWarehouseNames = ExcelUtils.getDuplicateElements(dbWarehouseNames);//取出存在重复的username
            }

            //取出excel和db中所有重复的code
            List<String> excelWarehouseCodes = sysWarehouseList.stream()
                    .map(SysWarehouseImportDTO::getWarehouseCode)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbWarehouseCodes = this.getAllWarehouseCode();//获取系统中所有的Warehousecode
            List<String> duplicateWarehouseCodes = new ArrayList<>(); // 存放存在重复的Warehousecode，用于定位重复存放存在重复的warehouseName的行

            if (dbWarehouseCodes.size() > 0 && excelWarehouseCodes.size() > 0) {
                dbWarehouseCodes.addAll(excelWarehouseCodes);//合并
                duplicateWarehouseCodes = ExcelUtils.getDuplicateElements(dbWarehouseCodes);//取出存在重复的username
            }

            // 服务类型(字典 warehouse_type)
            List<SysDictionary> dictionaryList =  sysDictionaryService.getDictByTypeCode("warehouse_type");
            Map<String, Integer> warehouseTypeMap = dictionaryList.stream()
                    .collect(Collectors.toMap(SysDictionary::getDicName, SysDictionary::getId, (v1, v2) -> v2));


            int index = 1;
            for (SysWarehouseImportDTO sysWarehouseDTO : sysWarehouseList) {
                index ++;
                // check
                StringBuilder stringBuilder = new StringBuilder();
                ExcelErrRowDTO excelErrRowDO= new ExcelErrRowDTO();

                // 参数校验
                stringBuilder.append(ValidatorUtils.validateExcel(sysWarehouseDTO));

                // 检验warehouseName 是否重复
                if(duplicateWarehouseNames.contains(sysWarehouseDTO.getWarehouseName())){
                    stringBuilder.append("仓库名称已经存在，请勿重复！");
                }
                // 检验warehouseCode 是否重复
                if(duplicateWarehouseCodes.contains(sysWarehouseDTO.getWarehouseCode())){
                    stringBuilder.append("仓库编号已经存在，请勿重复！");
                }

                // 仓库类型
                if(StringUtils.isNotEmpty(sysWarehouseDTO.getWarehouseTypeName())){
                    Integer typeId = warehouseTypeMap.get(sysWarehouseDTO.getWarehouseTypeName());
                    if(typeId==null){
                        stringBuilder.append("仓库类型:"+sysWarehouseDTO.getWarehouseTypeName()+",在系统中不存在");
                    }
                    sysWarehouseDTO.setWarehouseType(typeId);
                }

                // 将错误行信息保存到list
                String errMsg = stringBuilder.toString();
                if(StringUtils.isNotEmpty(errMsg)){
                    excelErrRowDO.setRowIndex(index);
                    excelErrRowDO.setErrMessage(errMsg);
                    errRowDOs.add(excelErrRowDO);
                    continue;
                }
                //保存
                SysWarehouse warehouse = new SysWarehouse();
                BeanUtils.copyProperties(sysWarehouseDTO,warehouse);
                sysWarehouses.add(warehouse);
            }
            saveBatch(sysWarehouses);

            // 导出错误行
            String errFileUrl = ExcelUtils.exportErrRows(errRowDOs,multipartFile,sysFileHisService);
            result.put("errFileUrl",errFileUrl);
        }
        return result;
    }

    @Override
    public void insertOrUpdateBatch(List<SysWarehouse> sysWarehouseList) {
        baseMapper.insertOrUpdateBatch(sysWarehouseList);
    }

    private List<String> getAllWarehouseName() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("warehouse_name");
        List<SysWarehouse> userList = this.list();
        List<String> names = userList.stream().map(SysWarehouse::getWarehouseName).collect(Collectors.toList());
        return names;
    }

    private List<String> getAllWarehouseCode() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("warehouse_code");
        List<SysWarehouse> userList = this.list();
        List<String> codes = userList.stream().map(SysWarehouse::getWarehouseCode).collect(Collectors.toList());
        return codes;
    }
}




